package org.hentai.tri.grpc.server;

import io.grpc.*;
import org.apache.dubbo.common.context.Lifecycle;
import org.hentai.tri.grpc.service.HentaiGrpcImpl;

import java.io.IOException;
import java.util.Objects;

public class HentaiGrepServer implements Lifecycle {

    private final int port;

    private Server server;

    public HentaiGrepServer(int port) {
        this.port = port;
    }

    public static void main(String[] args) throws IOException, InterruptedException {
        HentaiGrepServer grepServer = new HentaiGrepServer(50051);
        grepServer.initialize();
        grepServer.start();
        System.in.read();
    }

    @Override
    public void initialize() throws IllegalStateException {
        this.server = ServerBuilder.forPort(port)
                .addService(new HentaiGrpcImpl())
                .intercept(new EchoAttachmentInterceptor())
                .build();
    }

    @Override
    public void start() throws IllegalStateException {
        try {
            server.start();
            System.out.printf("Grpc server started at port %s%n", port);
        } catch (Exception e) {
            throw new IllegalStateException("Server grpc start failed", e);
        }
    }

    @Override
    public void destroy() throws IllegalStateException {
        server.shutdown();
    }

    private static class EchoAttachmentInterceptor implements ServerInterceptor {
        @Override
        public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> serverCall, Metadata metadata, ServerCallHandler<ReqT, RespT> serverCallHandler) {
            ForwardingServerCall.SimpleForwardingServerCall<ReqT, RespT> forwardingServerCall = new ForwardingServerCall.SimpleForwardingServerCall<>(serverCall) {
                @Override
                public void close(Status status, Metadata trailers) {
                    final String key = "hentai-attachment";
                    final Metadata.Key<String> metaKey = Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER);
                    if (metadata.containsKey(metaKey)) {
                        trailers.put(metaKey, String.format("hentai %s", Objects.requireNonNull(metadata.get(metaKey))));
                    }

                    super.close(status, trailers);
                }
            };

            return serverCallHandler.startCall(forwardingServerCall, metadata);
        }
    }
}
